﻿namespace Sai.Core.Introspection
{
	using System;
	using System.Collections.Generic;
	using System.Linq;

	public class MethodDeclarationCollection : System.Collections.ObjectModel.Collection<MethodDeclaration>
	{
		public MethodDeclarationCollection()
			: base()
		{
		}

		public MethodDeclarationCollection(IList<MethodDeclaration> methods)
			: base(methods)
		{
		}

        /// <summary>
        /// List of all "distinct" methods in the collection.
        /// Overloaded methods are represented by a single entry.
        /// </summary>
		public IList<string> DistinctMethods
		{
			get
			{
                HashSet<string> distinct = new HashSet<string>();

				foreach (var method in this)
				{
                    distinct.Add(method.Name);
				}

				return distinct.ToList();
			}
		}

        /// <summary>
        /// List names of methods which have overloads in the collection.
        /// </summary>
        public IList<string> OverloadedMethods
        {
            get
            {
                List<string> overloads = new List<string>();

                overloads.AddRange(this.DistinctMethods.Where(x => this.OverloadsFor(x).Count > 1));

                return overloads;
            }
        }

        /// <summary>
        /// List methods which do not have overloads in the collection.
        /// </summary>
        public MethodDeclarationCollection NonOverloadedMethods
        {
            get
            {
                MethodDeclarationCollection notOverloaded = new MethodDeclarationCollection();

                foreach (var method in this)
                {
                    var existing = this.OverloadsFor(method);

                    if (existing != null && existing.Count == 1)
                    {
                        notOverloaded.Add(method);
                    }
                }

                return notOverloaded;
            }
        }

		public void Sort()
		{
			this.OrderBy(x => x.Name); 
		}

		public ICollection<Signature> OverloadsFor(string methodName)
		{
            List<Signature> overloads = new List<Signature>();

            foreach (var method in this)
            {
                if (method.Matches(methodName))
                {
                    overloads.Add(method.Signature);
                }
            }

            return overloads;
		}

        public ICollection<Signature> OverloadsFor(MethodDeclaration m)
		{
			return this.OverloadsFor(m.Name);
		}
	}
}
